import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
import {BaseTreeService} from '@sb/base/core/service/base-tree.service';
import {BaseTreeComponent, ReturnForm} from '@sb/base';
import {NzMessageService} from 'ng-zorro-antd';
import {SysConfigService} from '../service/sys-config.service';
import {SysConfigSearchForm} from '../entity/sys-config-search-form';
import {SysConfigTreeNode} from '../entity/sys-config-tree-node';
import {DomSanitizer} from '@angular/platform-browser';
import {Observable} from 'rxjs';
import {NzTreeNode} from 'ng-zorro-antd/core/tree/nz-tree-base-node';

@Component({
    selector: 'sys-config-tree-panel',
    templateUrl: './sys-config-tree-panel.component.html',
    styleUrls: ['./sys-config-tree-panel.component.less'],
    providers: [
        {
            provide: BaseTreeService,
            useClass: SysConfigService
        }
    ]
})
export class SysConfigTreePanelComponent implements OnInit {

    typeIcon = {
        PAGE: 'dr:hy-application',
        CATEGORY: 'dr:hy-module',
        ITEM: 'dr:hy-menu',
        FIELD_SET: 'dr:hy-menu'
    };

    searchForm: SysConfigSearchForm = {
        parentId: '-1'
    };

    activeNode: SysConfigTreeNode;

    @ViewChild(BaseTreeComponent, {static: true})
    baseTree: BaseTreeComponent;

    @Output()
    selectNode = new EventEmitter<NzTreeNode>();


    @Input()
    searchConfig: {};

    @Input()
    customLoadMethod: (parentId: string, searchConfig: any, maxLevel: number, rmMenuTreeService: SysConfigService) => Observable<ReturnForm<SysConfigTreeNode[]>>;

    @Input()
    showRoot = false;

    @Input()
    checkable = false;

    @Input()
    draggable = false;

    @Input()
    showSearch = false;

    @Input()
    checkedWhileClick = true;


    constructor(
        private message: NzMessageService,
        private sanitizer: DomSanitizer) {
    }

    ngOnInit(): void {
    }

    onSelectNode(nzTreeNode: NzTreeNode): void {
        this.selectNode.emit(nzTreeNode);
    }

    onCheckNode(checkTreeNode: NzTreeNode): void {
        const currentChecked = checkTreeNode.isChecked;
        const menuTreeNode = checkTreeNode.origin as SysConfigTreeNode;
        if (menuTreeNode.type === 'PERMISSION') {
            if (currentChecked) {
                checkTreeNode.parentNode.isChecked = true;
                this.onCheckNode(checkTreeNode.parentNode);
            }
            return;
        }
        // 1、向上处理。
        {
            let parentNode: NzTreeNode = checkTreeNode;
            do {
                parentNode = parentNode.parentNode;
                if (parentNode == null) {
                    break;
                }
                let check = false;
                let uncheck = false;
                let halfcheck = false;
                for (const oneNode of parentNode.children) {
                    if (oneNode.isChecked) {
                        check = true;
                    } else {
                        uncheck = true;
                    }
                    if (oneNode.isHalfChecked) {
                        halfcheck = true;
                    }
                }
                parentNode.isChecked = check;
                parentNode.isHalfChecked = halfcheck || (check && uncheck);
            } while (true);
        }
        // 2、向下处理。
        {
            const nodes: NzTreeNode[] = [checkTreeNode];
            let index = 0;
            while (index < nodes.length) {
                const oneNode = nodes[index++];
                const nodeOptions = oneNode.origin as SysConfigTreeNode;
                oneNode.isChecked = currentChecked;
                oneNode.isHalfChecked = false;

                if (nodeOptions.type === 'MENU') {
                    for (const tempNode of oneNode.children) {
                        // tempNode.isDisabled = !currentChecked;
                        if (!currentChecked) {
                            tempNode.isChecked = currentChecked;
                            tempNode.isHalfChecked = false;
                        }
                    }
                    continue;
                }
                nodes.push(...oneNode.children);
            }
        }
    }

    beforeDrop(dragNode: SysConfigTreeNode, targetNode: SysConfigTreeNode): boolean {
        const dragNodeOptions = dragNode.origin;
        const targetNodeOptions = targetNode.origin;
        if (dragNodeOptions.type === 'root') {
            return false;
        } else if (dragNodeOptions.type === 'APPLICATION') {
            if (targetNodeOptions.type !== 'root') {
                return false;
            }
        } else if (dragNodeOptions.type === 'MODULE' ||
            dragNodeOptions.type === 'MENU') {
            if (targetNodeOptions.type !== 'APPLICATION' &&
                targetNodeOptions.type !== 'MODULE') {
                return false;
            }
        }
        return true;
    }


    getSvgHtml(picture: string) {
        return this.sanitizer.bypassSecurityTrustHtml(picture);
    }

    reload() {
        return this.baseTree.reload();
    }

    reloadNode(nodeId: string): Observable<any> {
        return this.baseTree.reloadNode(nodeId);
    }

    triggerClick(id: string) {
        this.baseTree.triggerClick(id);
    }

    checkNodeIds(menuIds: string[]) {
        for (const menuId of menuIds) {
            const treeNode = this.baseTree.nzTree.getTreeNodeByKey(menuId);
            treeNode.isChecked = true;
            this.onCheckNode(treeNode);
        }
    }
}
